'\"! tbl | mmdoc
'\"macro stdmacro
.\"
.\" Copyright (c) 2016-2018 Red Hat.
.\"
.\" This program is free software; you can redistribute it and/or modify it
.\" under the terms of the GNU General Public License as published by the
.\" Free Software Foundation; either version 2 of the License, or (at your
.\" option) any later version.
.\"
.\" This program is distributed in the hope that it will be useful, but
.\" WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
.\" or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
.\" for more details.
.\"
.TH PMLOOKUPLABELS 3 "PCP" "Performance Co-Pilot"
.SH NAME
\f3pmLookupLabels\f1,
\f3pmGetInstancesLabels\f1,
\f3pmGetItemLabels\f1,
\f3pmGetClusterLabels\f1,
\f3pmGetInDomLabels\f1,
\f3pmGetDomainLabels\f1,
\f3pmGetContextLabels\f1 \- retrieve labels associated with performance metric values
.SH "C SYNOPSIS"
.ft 3
#include <pcp/pmapi.h>
.sp
int pmLookupLabels(pmID \fIpmid\fP, pmLabelSet **\fIlabelsets\fP);
.sp
int pmGetInstancesLabels(pmInDom \fIindom\fP, pmLabelSet **\fIlabelsets\fP);
.br
int pmGetItemLabels(pmID \fIpmid\fP, pmLabelSet **\fIlabelsets\fP);
.br
int pmGetClusterLabels(pmID \fIpmid\fP, pmLabelSet **\fIlabelsets\fP);
.br
int pmGetInDomLabels(pmInDom \fIindom\fP, pmLabelSet **\fIlabelsets\fP);
.br
int pmGetDomainLabels(int \fIdomain\fP, pmLabelSet **\fIlabelsets\fP);
.br
int pmGetContextLabels(pmLabelSet **\fIlabelsets\fP);
.sp
cc ... \-lpcp
.ft 1
.SH "PYTHON SYNOPSIS"
.ft 3
.ad l
.hy 0
from pcp import pmapi
.sp
\fIlabelsets\fP = pmapi.pmContext().pmLookupLabels(\fIpmid\fP)
.sp
\fIlabelsets\fP = pmapi.pmContext().pmGetInstancesLabels(\fIindom\fP)
.br
\fIlabelsets\fP = pmapi.pmContext().pmGetItemLabels(\fIpmid\fP)
.br
\fIlabelsets\fP = pmapi.pmContext().pmGetClusterLabels(\fIpmid\fP)
.br
\fIlabelsets\fP = pmapi.pmContext().pmGetInDomLabels(\fIindom\fP)
.br
\fIlabelsets\fP = pmapi.pmContext().pmGetDomainLabels(\fIdomain\fP)
.br
\fIlabelsets\fP = pmapi.pmContext().pmGetContextLabels()
.hy
.ad
.ft 1
.SH DESCRIPTION
.de CR
.ie t \f(CR\\$1\fR\\$2
.el \fI\\$1\fR\\$2
..
Labels are
.IR name : value
pairs associated with performance metric values for the
purpose of attaching additional metric metadata to values.
This metadata is less structured and exists separately to
the metric descriptor available for every PCP metric from
.BR pmLookupDesc (3).
.PP
Much like the metric descriptor metadata, labels are an
integral part of the identity of each metric, and should
rarely, if ever, change.
.PP
The
.B pmLookupLabels
routine is a convenience interface providing retrieval for all
labels associated with a single performance metric identifier,
.IR pmid ,
.B except
labels at the instances level.
Labels at the instances level must be retrieved separately with a call to
.BR pmGetInstancesLabels
because different metric instances may have labels with the same label name.
The
.B pmLookupLabels
function performs no caching of labels internally.
.PP
For efficiency in communication and storage within the various
components of the PMCS (Performance Metrics Collection System),
labels are maintained using a hierarchy.
The set of labels associated with any individual metric value
consists of the union of labels from each of these sets of labels:
.TP 4n
1. Global labels (apply to all metric values from a host or archive context)
.TP 8n
.B pmGetContextLabels
provides the
.I labelsets
associated with all metric values from a given source (PMAPI context).
.TP 4n
2. Domain labels (apply to every metric within a PMDA)
.TP 8n
.B pmGetDomainLabels
provides the
.I labelsets
associated with the
.I domain
identifier.
.TP 4n
3. Instance Domain labels (apply to all metrics sharing that indom)
.TP 8n
.B pmGetInDomLabels
provides the
.I labelsets
associated with the instance domain identifier
.IR indom .
.TP 4n
4. Cluster labels (apply to a group of metrics within one domain)
.TP 8n
.B pmGetClusterLabels
provides the
.I labelsets
associated with the metric cluster (domain,cluster) identified by
.IR pmid .
.TP 4n
5. Item labels (apply to an individual performance metric)
.TP 8n
.B pmGetItemLabels
provides the
.I labelsets
associated with the metric item (domain,cluster,item) identified by
.IR pmid .
.TP 4n
6. Instance labels (apply to individual instances of a metric)
.TP 8n
.BR pmGetInstancesLabels
provides the set of instance identifiers and labels in
.I labelsets
for each instance associated with the instance domain identifier
.IR indom .
The return value indicates the number of elements in the result \- one
.I labelsets
for each instance.
.PP
These independent
.I labelsets
can be merged using
.BR pmMergeLabelSets (3)
to form the complete set of all labels associated with a given value.
Note that the label sets returned by
.B pmGetInstancesLabels
can be traversed but should not be merged because the label names are unlikely
to be unique for different instances of the given
.IR indom .
.SH LABEL SYNTAX
Labels are stored and communicated within PCP using JSONB format.
This format is a restricted form of JSON suitable for indexing
and other operations.
In JSONB form, insignificant whitespace is discarded,
and the order of label names is not preserved.
Within the PMCS a lexicographically sorted key space is always
maintained, however.
Duplicate label names are not permitted.
The label with highest precedence is the only one presented.
If duplicate names are presented at the same hierarchy level, only
one will be preserved (exactly which one wins is arbitrary, so do
not rely on this).
.PP
All \f2name\f1:\f2value\f1 pair(s) present will be converted to
JSONB form and merged with the existing set of labels for the
requested entity (context, domain, indom, metric or instance).
.PP
The label names are further constrained to the same set of rules
defined for
.BR PMNS
subtree names.
.PP
Each component in a label
.I name
must begin with an alphabetic character, and be followed by zero
or more characters drawn from the alphabetics, the digits and the
underscore (``_'') character.  For alphabetic characters in a
.IR name ,
upper and lower case are distinguished.
.PP
The
.I value
of a label offers significantly more freedom, and may be any valid
value as defined by the JSON (\c
.IR https://www.json.org )
specification.
Redundant whitespace is always removed within the PMCS.
.SH PRECEDENCE
The complete set of labels associated with any metric value is
built from several sources and duplicate label names may exist
at any point in the source hierarchy.
However, when evaluating the label set (merging labels from the
different sources) the JSONB concept of only presenting unique
labels is used.
It is therefore important to define precedence rules in order
that a deterministic set of uniquely named labels can be defined.
.PP
As a rule of thumb, the labels closest to PMNS leaf nodes and
metric values take precedence:
.TP 4n
1. Global context labels
(as reported by the
.I pmcd.labels
metric) are the lowest precedence.
.TP 4n
2. Domain labels
(for all metrics and instances from a PMDA) are the next highest precedence.
.TP 4n
3. Instance Domain labels
associated with an InDom are the next highest precedence.
.TP 4n
4. Metric cluster labels
associated with a PMID cluster are the next highest precedence.
.TP 4n
5. Metric item labels
associated with an individual PMID are the next highest precedence.
.TP 4n
6. Instance labels
associated with a metric instance identifier have highest precedence.
.SH DATA STRUCTURES
The primary output from
.B pmLookupLabels
is returned in the
argument
.I labelsets
as an array, using the following component data structures;
.PP
.ft CR
.nf
.in +0.5i
struct {
    uint     name : 16;      /* label name offset in JSONB string */
    uint     namelen : 8;    /* length of name excluding the null */
    uint     flags : 8;      /* information about this label */
    uint     value : 16;     /* offset of the label value */
    uint     valuelen : 16;  /* length of value in bytes */
} pmLabel;

struct {
    uint     inst;           /* PM_IN_NULL or the instance ID */
    int      nlabels;        /* count of labels or error code */
    char     *json;          /* JSON formatted labels string */
    uint     jsonlen : 16;   /* JSON string length byte count */
    uint     padding : 16;   /* zero, reserved for future use */
    pmLabel  *labels;        /* indexing into the JSON string */
} pmLabelSet;
.in
.fi
.ft 1
.PP
The
.CR pmLabel
provides information about an individual label.
This includes the offsets to
the start of its
.CR name
and
.CR value
in the
.CR json
string of a
.CR pmLabelSet ,
their respective lengths, and also any informative flags associated
with the label (describing where it lies in the hierarchy of labels,
and whether it is an intrinsic or extrinsic label).
.PP
Building on this, the
.CR pmLabelSet
provides information about the set of labels associated with an
entity (context, domain, indom, metric cluster, item or instance).
The entity will be from any one level of the label hierarchy.
If at the lowest hierarchy level (which happens to be highest
precedence \- PM_LABEL_INSTANCES) then the
.CR inst
field will contain an actual instance identifier instead of PM_IN_NULL.
.PP
The
.CR nlabels
field describes the number of labels (name:value pairs) that can be
found in both the accompanying
.CR json
string (which is JSONB format \- no unnecessary whitespace and with
no duplicate label names)
and the accompanying
.CR labels
array (which has
.CR nlabels
elements).
.SH EXAMPLES
Consider a deployment with global labels (assume $PCP_SYSCONF_DIR
is set to its usual location of
.IR /etc/pcp )
as follows:
.P
.ft CR
.nf
.B "$ cat /etc/pcp/labels/*"
{
  "tier": "production",
  "datacenter": "hkg",
  "services": ["indexer","database"]
}
.fi
.ft 1
.P
Use
.B pminfo
to form the merged
.I labelsets
for several
.BR pmdasample (1)
metrics as follows:
.P
.ft CR
.nf
.B "$ pminfo -m -f --labels sample.rapid sample.colour sample.mirage"
.P
sample.rapid PMID: 30.0.64
.in +0.5i
value 800000000
.br
labels {"agent":"sample","datacenter":"sydney","hostname":"acme.com","measure":"speed","role":"testing","services":["indexer","database"],"tier":"production","units":"metres per second","unitsystem":"SI"}
.in
.fi
.P
.ft CR
.nf
sample.colour PMID: 30.0.5
.in +0.5i
inst [0 or "red"] value 101
.br
inst [1 or "green"] value 202
.br
inst [2 or "blue"] value 303
.br
inst [0 or "red"] labels {"agent":"sample","datacenter":"syd","hostname":"acme.com","model":"RGB","role":"testing","services":["indexer","database"],"tier":"production"}
.br
inst [1 or "green"] labels {"agent":"sample","datacenter":"syd","hostname":"acme.com","model":"RGB","role":"testing","services":["indexer","database"],"tier":"production"}
.br
inst [2 or "blue"] labels {"agent":"sample","datacenter":"syd","hostname":"acme.com","model":"RGB","role":"testing","services":["indexer","database"],"tier":"production"}
.in
.fi
.P
.ft CR
.nf
sample.mirage PMID: 29.0.37
.in +0.5i
inst [0 or "m-00"] value 99
.br
inst [0 or "m-00"] labels {"agent":"sample","datacenter":"sydney","hostname":"acme.com","role":"testing","services":["indexer","database"],"tier":"production","transient":false}
.in
.fi
.ft 1
.P
Here,
.B pminfo
has merged the separate sets of labels returned from
.B pmGetContextLabels
(\c
.IR name s:
datacenter, hostname, services, tier),
.B pmGetDomainLabels
(\c
.IR name s:
role, agent),
.B pmGetInDomLabels
(\c
.IR name s:
model),
.B pmGetItemLabels
(\c
.IR name s:
units, unitsystem)
and
.B pmGetInstancesLabels
(\c
.IR name s:
transient)
to form the complete set for each of the metrics.
.SH "PYTHON EXAMPLE"
.ft 3
.nf
#!/usr/bin/env pmpython

import sys
from pcp import pmapi
import cpmapi as c_api

ctx = pmapi.pmContext(c_api.PM_CONTEXT_HOST, "local:")

for metric in sys.argv[1:]:
    pmid = ctx.pmLookupName(metric)[0]
    desc = ctx.pmLookupDescs(pmid)[0]

    print("== label sets for %s ==" % metric)
    labelSetList = ctx.pmLookupLabels(pmid)
    # class pmLabelSet has a __str__ handler
    for labelSet in labelSetList:
        print("\t%s" % labelSet)
    ctx.pmFreeLabelSets(labelSetList)

    if desc.contents.indom != c_api.PM_INDOM_NULL:
        print("== instances label sets for %s ==" % metric)
        labelSetList = ctx.pmGetInstancesLabels(desc.contents.indom)
        for labelSet in labelSetList:
            print("\t%s" % labelSet)
        ctx.pmFreeLabelSets(labelSetList)
.ft 2
.SH DIAGNOSTICS
On success these interfaces all return the number of elements in
the
.I labelsets
array.
associated with performance metrics.
The memory associated with
.I labelsets
should be released using
.BR pmFreeLabelSets (3)
when no longer needed.
.PP
Only in the case of
.B pmLookupLabels
will the resulting
.I labelsets
be a merged set of labels from all hierarchy levels
(except at the instances level, as described above).
.PP
For the other routines, except for
.BR pmGetInstancesLabels ,
if no labels exist at all for the requested hierarchy level the
return code will be zero and no space will have been allocated.
.PP
In the case of
.BR pmGetInstancesLabels ,
which can return multiple elements in its
.I labelsets
result (one set of labels for each instance), the
.I nlabels
field may be either zero indicating no labels for that instance,
or a positive count of labels, or a negative PMAPI error code.
.PP
Note that it is mandatory for a call to
.B pmGetInstancesLabels
to be preceded by a call to
.BR pmGetInDom (3)
to ensure the instances have been resolved within the PMDA.
.PP
If no result can be obtained,
e.g. due to IPC failure using the current PMAPI context then
.B pmGetInstancesLabels
will return a negative error code which may be examined using
.PP
A successful return from the Python API always provides the
.I labelsets
result in the form of a list, for all labels functions.
On error a
.B pmErr
exception is raised containing the error code and diagnostic.
.BR pmErrStr (3).
.SH SEE ALSO
.BR pmcd (1),
.BR PMAPI (3),
.BR pmFetch (3),
.BR pmGetInDom (3),
.BR pmLookupDesc (3),
.BR pmLookupName (3),
.BR pmFreeLabelSets (3),
.BR pmMergeLabelSets (3),
.BR pmNewContext (3)
and
.BR labels.conf (5).

.\" control lines for scripts/man-spell
.\" +ok+ labelSetList labelSet
.\" +ok+ desc ctx {from Python variables}
.\" +ok+ unitsystem metres sydney RGB hkg syd {from labels}
.\" +ok+ pmContext pmErr {from Python class}
.\" +ok+ valuelen namelen uint {from pmLabel}
.\" +ok+ nlabels jsonlen {from pmLabelSet}
.\" +ok+ __str__ cpmapi argv c_api sys {from Python example}
